[READ-ONLY] a fast, modern browser for the npm registry
at main 52 lines 1.7 kB view raw
1import * as v from 'valibot' 2import { PackageVersionQuerySchema } from '#shared/schemas/package' 3import type { PackageFileTreeResponse } from '#shared/types' 4import { CACHE_MAX_AGE_ONE_YEAR, ERROR_FILE_LIST_FETCH_FAILED } from '#shared/utils/constants' 5 6/** 7 * Returns the file tree for a package version. 8 * 9 * URL patterns: 10 * - /api/registry/files/packageName/v/1.2.3 - required version 11 * - /api/registry/files/@scope/packageName/v/1.2.3 - scoped package 12 */ 13export default defineCachedEventHandler( 14 async event => { 15 // Parse package name and version from URL segments 16 // Patterns: [pkg, 'v', version] or [@scope, pkg, 'v', version] 17 const pkgParamSegments = getRouterParam(event, 'pkg')?.split('/') ?? [] 18 19 const { rawPackageName, rawVersion } = parsePackageParams(pkgParamSegments) 20 21 try { 22 const { packageName, version } = v.parse(PackageVersionQuerySchema, { 23 packageName: rawPackageName, 24 version: rawVersion, 25 }) 26 27 const jsDelivrData = await fetchFileTree(packageName, version) 28 const tree = convertToFileTree(jsDelivrData.files) 29 30 return { 31 package: packageName, 32 version, 33 default: jsDelivrData.default ?? undefined, 34 tree, 35 } satisfies PackageFileTreeResponse 36 } catch (error: unknown) { 37 handleApiError(error, { 38 statusCode: 502, 39 message: ERROR_FILE_LIST_FETCH_FAILED, 40 }) 41 } 42 }, 43 { 44 // Files for a specific version never change - cache permanently 45 maxAge: CACHE_MAX_AGE_ONE_YEAR, // 1 year 46 swr: true, 47 getKey: event => { 48 const pkg = getRouterParam(event, 'pkg') ?? '' 49 return `files:v1:${pkg.replace(/\/+$/, '').trim()}` 50 }, 51 }, 52)